package org.vectrics.recruiter.struts.admin;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import javax.servlet.jsp.JspException;

import org.apache.struts.action.ActionForm;
import org.vectrics.SystemException;
import org.vectrics.common.db.SimpleCodedObject;
import org.vectrics.common.util.DateUtil;
import org.vectrics.common.util.StringUtils;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.history.HistoryProvider;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.job.Job;
import org.vectrics.recruiter.job.JobStatus;
import org.vectrics.recruiter.job.JobStatusReasonType;
import org.vectrics.recruiter.job.JobStatusSubType;
import org.vectrics.recruiter.job.JobStatusType;
import org.vectrics.recruiter.struts.JobStatusForm;
import org.vectrics.recruiter.struts.tag.JobDetailDisplayOptions;
import org.vectrics.struts.Request;
import org.vectrics.struts.UserBufferManager;
import org.vectrics.struts.VectricsActionData;
import org.vectrics.struts.VectricsStrutsAction;
import org.vectrics.user.Person;


public class SaveJobStatusAction extends VectricsStrutsAction {
	public static final long serialVersionUID = 434642223;
   
    public static final String CURRENT_JOB_KEY = "jobId";    
	
    public SaveJobStatusAction() {
    	super();
    }


	public String doExecute(VectricsActionData actionData)	throws JspException {
		Request request = actionData.getRequest();
		ActionForm form = actionData.getForm();	
		Person person = null;
		JobStatusForm jobForm = (JobStatusForm)form;
		String forwardCode = "success";
		boolean activated = false;
		boolean deactivated = false;

		if (actionData.wasButtonPressed("cancel") == true) {
			JobDetailDisplayOptions options = new JobDetailDisplayOptions();
			options.setDefaultOptions();
		   	
			JobSearchActionHelper helper = new JobSearchActionHelper();
		    helper.storeDisplayOptions(actionData.getRequest(), options);			
	
		    log.debug("Cancel button pressed.");
		    forwardCode = "cancel";
			if ((jobForm.getJobId() == null) || (jobForm.getJobId().trim().equals(""))) {
				forwardCode = "cancel.new";
			}

		} else {
			ThreadProperties.getSession().clear();
			try {
				person = CoreServiceLocator.getUserAuthService().getAuthorizedPerson(ThreadProperties.getDomain(), request);
			}
			catch (Exception ex) {
				log.error("Exception finding auth user", ex);
				throw new JspException("Exception finding auth user", ex);
			}
	
	        log.debug("execute() called, reading http parameters");
	        Job job = null;
	        
			if ((jobForm.getJobId() == null) || (jobForm.getJobId().trim().equals(""))) {
				log.debug("execute() - creating new job - job id param not passed to this action.");
				job = new Job();
	            
				log.debug("execute() - new job id = " + job.getId());
			}
			else {
				log.debug("execute() - attempting to find job.");
				try {
				    Long jobId = new Long(jobForm.getJobId());
					job = RecruitServiceLocator.getJobProvider().findJob(jobId);
				} catch (Exception de) {
					log.error("Could not find job: " + jobForm.getJobId());
					throw new JspException(de);
				}
	            
				if (person == null) {
					throw new JspException("Could not find user logged in.");
				}
	
				if (job == null) {
					log.error("execute() - job ID not found: " + jobForm.getJobId());
				}
			}
			
			boolean statusChanged = false;
			JobStatusType prevStatusType = null;
			JobStatusType newStatusType = null;
			if (StringUtils.isNullOrBlank(jobForm.getStatusTypeCode()) == false) {
				newStatusType = RecruitServiceLocator.getJobProvider()
						.findJobStatusType(jobForm.getStatusTypeCode(), job.getCompany().getDomain());
				if (job.getCurrentStatus() != null)
					prevStatusType = job.getCurrentStatus().getStatusType();
				
				if (prevStatusType == null) {
					if ((newStatusType.getSubStatusType().getCode().equals(JobStatusSubType.SUB_STATUS_PUBLIC_POSTED))
							|| (newStatusType.getSubStatusType().getCode().equals(JobStatusSubType.SUB_STATUS_INTERNAL_POSTED))){
						activated = true;
					} else {
						activated = false;
					}
					statusChanged = true;
				} else {
					if (newStatusType.getCode().equals(prevStatusType.getCode()) == false) {
						statusChanged = true;
						if ((newStatusType.getSubStatusType().getCode().equals(JobStatusSubType.SUB_STATUS_PUBLIC_POSTED))
								|| (newStatusType.getSubStatusType().getCode().equals(JobStatusSubType.SUB_STATUS_INTERNAL_POSTED))) {
							activated = true;
						} else {
							if ((prevStatusType.getSubStatusType().getCode().equals(JobStatusSubType.SUB_STATUS_PUBLIC_POSTED))
									|| (prevStatusType.getSubStatusType().getCode().equals(JobStatusSubType.SUB_STATUS_INTERNAL_POSTED))) {
								deactivated = true;
							}
						}
				    }
				}
			} else {
				if (job.getCurrentStatus() == null) {
					statusChanged = true;
					Domain domain = job.getCompany().getDomain();
					JobStatusType createdStatusType = RecruitServiceLocator.getJobProvider()
						.findJobStatusType(JobStatusType.STATUS_CREATED, domain);
					job.setStatus(createdStatusType, ThreadProperties.getPerson());
					newStatusType = job.getCurrentStatus().getStatusType();
					prevStatusType = null;
				}
			}
			
			if (statusChanged) {
				job.setStatus(newStatusType, actionData.getAuthPerson());
			}
			
	
			log.debug("execute() - finished saving job info.");
			RecruitServiceLocator.getJobProvider().updateJob(job);
			ThreadProperties.forcedCommit();

			jobForm.setJobId(job.getId().toString());
			request.setAttribute("jobId", job.getId().toString());

			jobForm.setJobId(job.getId().toString());
			request.setAttribute("job", job);
			
			try {
				if (activated) {
					HistoryProvider.getInstance().createHistory(Job.OBJECT_TYPE, job.getId().toString(), 
							"job_activate", 
					        person, "Activated Job");
				}
				if (deactivated) {
					HistoryProvider.getInstance().createHistory(Job.OBJECT_TYPE, job.getId().toString(), 
							"job_deactivate", 
					        person, "Deactivated Job");
				}
				ThreadProperties.forcedCommit();
			}
			catch (Exception de) {
				log.error("Exception recording activation history", de);
			}
			
			UserBufferManager bufferManager = new UserBufferManager();	
		    bufferManager.addBufferedObject(request, job);
		    
		    if ((statusChanged) || ((newStatusType != null) && (newStatusType.getCode().equals(JobStatusType.STATUS_POSTED_PENDING)))) {
		    	int numberOfReasons = prepareUserSelectsStatusReason(job, prevStatusType, actionData);
		    	if (numberOfReasons > 1) {
		    		// This forward code brings up a form that allows selection of a reason.
		    		forwardCode = "select.status.reason";
		    	}
		    }
		    
		}
		ThreadProperties.forcedCommit();
		return (forwardCode);
    }

    private int prepareUserSelectsStatusReason(Job job, JobStatusType inPreviousStatusType, 
			VectricsActionData actionData) {
		JobStatusType previousStatusType = inPreviousStatusType;
		// Create ActionForm to be passed to HTML edit.
		JobStatusReasonForm reasonForm = new JobStatusReasonForm();
		reasonForm.setJobId(job.getId().toString());
		reasonForm.setJobReferenceCode(job.getReferenceId());
		reasonForm.setJobStatusName(job.getCurrentStatus().getStatusType().getDescription(actionData.getLocale()));
		reasonForm.setJobTitle(job.getTitle());
		reasonForm.setJobTitle(job.getCurrentStatus().getDescription());
		Date postDate = DateUtil.addDaysToToday(5);
		reasonForm.setPendingPostedDate(CoreServiceLocator.getDateFormat().getDateFormatRoundToDay(actionData.getLocale()).format(postDate));
		reasonForm.setJobStatusReasonTypeCode(job.getCurrentStatus().getStatusReasonType().getCode());
		
		actionData.setRequestForm(reasonForm);
		
		// Make array for reason selection
		Collection reasonTypes = null;
		
		// If status was not changed, look at job status history to find prev. status to 
		// aid in coming up with status reason list for user selection.
		if ((previousStatusType != null) 
				&& (previousStatusType.getCode().equals(job.getCurrentStatus().getStatusType().getCode()))) {
			// Find previous status for job
			JobStatus prevStatus = job.getPreviousStatus(job.getCurrentStatus());
			while ((prevStatus != null) 
					&& (prevStatus.getStatusType().getCode().equals(job.getCurrentStatus().getStatusType().getCode()))) {
				prevStatus = job.getPreviousStatus(job.getCurrentStatus());
			}
			if (prevStatus == null) {
				previousStatusType = null;
			} else {
				previousStatusType = prevStatus.getStatusType();
			}
		}
		
		if (previousStatusType == null) {
			reasonTypes = RecruitServiceLocator.getJobProvider().findStatusReasonTypes(job.getDomain(), null, job.getCurrentStatus().getStatusType().getCode());
		} else {
			reasonTypes = RecruitServiceLocator.getJobProvider().findStatusReasonTypes(job.getDomain(), previousStatusType.getCode(), job.getCurrentStatus().getStatusType().getCode());
		}
		
		
		Collection reasonTypeDescriptions = new ArrayList();
		Iterator iter = reasonTypes.iterator();
		while (iter.hasNext()) {
			JobStatusReasonType reasonType = (JobStatusReasonType)iter.next();
			SimpleCodedObject reasonTypeWithDescription = new SimpleCodedObject();
			reasonTypeWithDescription.setCode(reasonType.getCode());
			reasonTypeWithDescription.setName(actionData.getPhrase(reasonType.getName()));
			reasonTypeDescriptions.add(reasonTypeWithDescription);
		}
		
		actionData.getRequest().setSessionAttribute("statusReasonTypes", reasonTypeDescriptions);
		if (reasonTypes.size() == 0)
			throw new SystemException("Exception, no reasons found for transition to " + job.getCurrentStatus().getStatusType().getCode());
		
		if (job.getCurrentStatus().getStatusType().getCode().equals(JobStatusType.STATUS_POSTED_PENDING))
			actionData.getRequest().setAttribute("showJobPostDate", "true");
		else
			actionData.getRequest().setAttribute("showJobPostDate", "false");
			
		return(reasonTypes.size());
	}
	
	
}
